package list

type Node[V any] struct {
	prev, next *Node[V]
	data       V
}

type DoublyLinkedList[V any] struct {
	head, tail *Node[V]
}

func (d *DoublyLinkedList[V]) InsertLast(val V) {
	node := &Node[V]{data: val}
	if d.tail == nil {
		d.head = node
		d.tail = node
		return
	}
	d.tail.next = node
	node.prev = d.tail

	d.tail = node
}

func (d *DoublyLinkedList[V]) InsertFirst(val V) {
	node := &Node[V]{data: val}
	if d.head == nil {
		d.head = node
		d.tail = node
		return
	}
	d.head.prev = node
	node.next = d.head
	d.head = node
}

func (d *DoublyLinkedList[V]) RemoveByIndex(index int) bool {
	if d.head == nil || index < 0 {
		return false
	}
	if index == 0 {
		if d.head == d.tail {
			d.head, d.tail = nil, nil
			return true
		}
		d.head.next.prev = nil
		d.head = d.head.next
		return true
	}

	current := d.head
	for i := 1; i < index; i++ {
		if current.next == nil {
			return false
		}
		current = current.next
	}

	delNode := current.next
	if delNode.next == nil {
		d.tail = current
	} else {
		delNode.next.prev = current
	}
	current.next = delNode.next
	return true
}

func (d *DoublyLinkedList[V]) GetFirst() *Node[V] {
	return d.head
}

func (d *DoublyLinkedList[V]) GetLast() *Node[V] {
	return d.tail
}
